<?php
declare(strict_types=1);

namespace src;

class Route
{
    protected $uri;
    protected $methods;

    /**
        +action: array:6 [▼
        "middleware" => array:2 [▼
        0 => "web"
        1 => "App\Http\Middleware\FooMiddleware"
        ]
        "uses" => "App\Http\Controllers\Home@detail"
        "controller" => "App\Http\Controllers\Home@detail"
        "namespace" => null
        "prefix" => ""
        "where" => []
        ]
     *
     *
     * @var
     */
    protected $action;

    protected $router;
    /**
     * @var Container
     */
    protected $container;
    protected $controller;

    public function __construct($methods, $uri, $action)
    {
        $this->uri = $uri;
        $this->methods = (array) $methods;
        $this->action['uses'] = $action;
    }

    public function methods()
    {
        return $this->methods;
    }

    public function uri()
    {
        if (empty($this->uri)){
            $this->uri = strchr($this->uri, "?");
        }
        return $this->uri;
    }

    public function setRouter(Router $router)
    {
        $this->router = $router;
        return $this;
    }

    public function setContainer(Container $container)
    {
        $this->container = $container;
        return $this;
    }

    /**
     * 添加中间件
     * @param $middleware
     * @return void
     */
    public function middleware($middleware = null)
    {
        if (is_null($middleware)){
            return (array) ($this->action['middleware'] ?? []);
        }
        if (! is_array($middleware)) {
            $middleware = func_get_args();
        }
        $this->action['middleware'] = array_merge(
            (array) ($this->action['middleware'] ?? []), $middleware
        );
        return $this;
    }

    public function run()
    {
        $this->container = $this->container ?: new Container;
        if (is_string($this->action['uses'])){
            return $this->runController();
        }
        return $this->runCallable();
    }

    protected function runController()
    {
        $action = explode('@', $this->action['uses'], 2);
        if (count($action) == 2){
            $this->controller = $this->container->make(ltrim($action[0], '\\'));
        }
        return (new ControllerDispatcher($this->container))->dispatch($this, $this->controller, $action[1]);
    }

    protected function runCallable()
    {
        return $this->action['uses']($this->container);
    }
}